
//
// 版权所有 (c) 2021-2023 JR
//
// 特此免费授予获得本软件的任何人以处理本软件的权利，但须遵守以下条件：在所有副本或重要部分的软件中必须包括上述版权声明和本许可声明。
//
// 软件按“原样”提供，不提供任何形式的明示或暗示的保证，包括但不限于对适销性、适用性和非侵权的保证。
// 在任何情况下，作者或版权持有人均不对任何索赔、损害或其他责任负责，无论是因合同、侵权或其他方式引起的，与软件或其使用或其他交易有关。

namespace EMC.VISITOR.Core.Service;

/// <summary>
/// 系统通知公告服务
/// </summary>
[ApiDescriptionSettings(Order = 380)]
public class SysNoticeService : IDynamicApiController, ITransient
{
    private readonly UserManager _userManager;
    private readonly SqlSugarRepository<SysUser> _sysUserRep;
    private readonly SqlSugarRepository<SysNotice> _sysNoticeRep;
    private readonly SqlSugarRepository<SysNoticeUser> _sysNoticeUserRep;
    private readonly SysOnlineUserService _sysOnlineUserService;
    private readonly SysOrgService _sysOrgService;

    public SysNoticeService(
        UserManager userManager,
        SqlSugarRepository<SysUser> sysUserRep,
        SqlSugarRepository<SysNotice> sysNoticeRep,
        SqlSugarRepository<SysNoticeUser> sysNoticeUserRep,
        SysOnlineUserService sysOnlineUserService,
        SysOrgService sysOrgService)
    {
        _userManager = userManager;
        _sysUserRep = sysUserRep;
        _sysNoticeRep = sysNoticeRep;
        _sysNoticeUserRep = sysNoticeUserRep;
        _sysOnlineUserService = sysOnlineUserService;
        _sysOrgService = sysOrgService;
    }

    /// <summary>
    /// 获取通知公告分页列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("获取通知公告分页列表")]
    public async Task<SqlSugarPagedList<SysNotice>> Page(PageNoticeInput input)
    {
        return await _sysNoticeRep.AsQueryable()
            .WhereIF(!string.IsNullOrWhiteSpace(input.Title), u => u.Title.Contains(input.Title.Trim()))
            .WhereIF(input.Type > 0, u => u.Type == input.Type)
            .WhereIF(!_userManager.SuperJR, u => u.CreateUserId == _userManager.UserId)
            .OrderBy(u => u.CreateTime, OrderByType.Desc)
            .ToPagedListAsync(input.Page, input.PageSize);
    }
    [ApiDescriptionSettings(Name = "GetNoticeCount"), HttpGet]
    [DisplayName("获取未读公告数量")]
    public async Task<dynamic> GetNoticeCount()
    {
        var noticeList = await _sysNoticeRep.AsSugarClient().Queryable<SysNoticeUser>()
            .Where(u => u.UserId == _userManager.UserId && u.ReadStatus == NoticeUserStatusEnum.UNREAD)
            .InnerJoin<SysUser>((u, sysUser) => u.UserId == sysUser.Id)
            .InnerJoin<SysNotice>((u, sysUser, notice) => u.NoticeId == notice.Id)
            .Select((u, sysUser, notice) => new
            {
                noticeId = u.NoticeId,
                title = notice.Title,
                content = notice.Content,
                u.UserId,
                u.PushComplate,
                u.AppJumpUrl
            })
            .ToListAsync();
        var list = noticeList.Select(r => new
        {
            r.noticeId,
            r.title,
            r.UserId,
            r.PushComplate,
            r.AppJumpUrl,
            content = r.content.NoHTML()
        }).ToList();
        return new { count = noticeList.Count, noticeList = list };
    }
    /// <summary>
    /// 增加通知公告
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "Add"), HttpPost]
    [DisplayName("增加通知公告")]
    public async Task<long> AddNotice(AddNoticeInput input)
    {
        var notice = input.Adapt<SysNotice>();
        await InitNoticeInfo(notice);
        return await _sysNoticeRep.Context.Insertable<SysNotice>(notice).ExecuteReturnSnowflakeIdAsync();
    }

    /// <summary>
    /// 更新通知公告
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "Update"), HttpPost]
    [DisplayName("更新通知公告")]
    public async Task UpdateNotice(UpdateNoticeInput input)
    {
        var notice = input.Adapt<SysNotice>();
        await InitNoticeInfo(notice);
        await _sysNoticeRep.UpdateAsync(notice);
    }

    /// <summary>
    /// 更新通知公告
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "UpdateNoticePush"), HttpPost]
    [DisplayName("更新通知公告推送完成")]
    public async Task UpdateNoticePush(List<SysNoticeUser> input)
    {
        input = input.Where(r => r.PushComplate == false).ToList();
        if (input.Count > 0)
        {
            input.ForEach(r =>
            {
                r.PushComplate = true;
            });
            await _sysNoticeRep.Context.MyUpdateable(input)
                .UpdateColumns(r => new { r.PushComplate })
                .WhereColumns(new string[] { nameof(SysNoticeUser.NoticeId), nameof(SysNoticeUser.UserId) }).ExecuteCommandAsync();
        }
    }

    /// <summary>
    /// 删除通知公告
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [UnitOfWork]
    [ApiDescriptionSettings(Name = "Delete"), HttpPost]
    [DisplayName("删除通知公告")]
    public async Task DeleteNotice(DeleteNoticeInput input)
    {
        await _sysNoticeRep.DeleteAsync(u => u.Id == input.Id);

        await _sysNoticeUserRep.DeleteAsync(u => u.NoticeId == input.Id);
    }

    #region 系统原先代码 2024-02-02 注释
    ///// <summary>
    ///// 发布通知公告
    ///// </summary>
    ///// <param name="input"></param>
    ///// <returns></returns>
    //[DisplayName("发布通知公告")]
    //public async Task Public(NoticeInput input)
    //{
    //    // 更新发布状态和时间
    //    await _sysNoticeRep.UpdateAsync(u => new SysNotice() { Status = NoticeStatusEnum.PUBLIC, PublicTime = DateTime.Now }, u => u.Id == input.Id);

    //    var notice = await _sysNoticeRep.GetFirstAsync(u => u.Id == input.Id);

    //    List<long> userIdList = new List<long>();
    //    // 通知到的人(所有账号)
    //    userIdList = await _sysUserRep.AsQueryable().Select(u => u.Id).ToListAsync();

    //    await _sysNoticeUserRep.DeleteAsync(u => u.NoticeId == notice.Id);
    //    var noticeUserList = userIdList.Select(u => new SysNoticeUser
    //    {
    //        NoticeId = notice.Id,
    //        UserId = u,
    //    }).ToList();
    //    await _sysNoticeUserRep.InsertRangeAsync(noticeUserList);

    //    // 广播所有在线账号
    //    await _sysOnlineUserService.PublicNotice(notice, userIdList);
    //} 
    #endregion

    #region 2024-02-02 启用
    /// <summary>
    /// 发布通知公告
    /// </summary>
    /// <param name="input"></param>
    /// <param name="sendLevel">
    /// 发送层级：
    /// 0. 包含当前层级一直往下
    /// 1. 当前层级
    /// 2. 当前层级的上一个层级
    /// 3. 当前层级的上一个层级和上两个层级
    /// </param>
    /// <returns></returns>
    [DisplayName("发布通知公告")]
    public async Task Public(NoticeInput input,int? sendLevel = 0)
    {
        // 更新发布状态和时间
        await _sysNoticeRep.UpdateAsync(u => new SysNotice() { Status = NoticeStatusEnum.PUBLIC, PublicTime = DateTime.Now }, u => u.Id == input.Id);

        var notice = await _sysNoticeRep.GetFirstAsync(u => u.Id == input.Id);

        List<long> userIdList = new List<long>();
        if (notice.Type == NoticeTypeEnum.ANNOUNCEMENT)
        {
            // 通知到的人(所有账号)
            userIdList = await _sysUserRep.AsQueryable().Select(u => u.Id).ToListAsync();
        }
        else
        {
            if (notice.ReceiveUserList != null && notice.ReceiveUserList.Count > 0)
                userIdList = notice.ReceiveUserList.Select(r => r.id).ToList();
            else if (notice.ReceiveOrgId.HasValue && notice.ReceiveOrgId > 0)
            {
                userIdList = await _sysOrgService.GetChildUserListWithSelfUserById(notice.ReceiveOrgId.Value);
            }
            if (userIdList.Count <= 0)
                throw Oops.Oh(ErrorCodeEnum.MP1002);
        }
        await _sysNoticeUserRep.DeleteAsync(u => u.NoticeId == notice.Id);
        var noticeUserList = userIdList.Select(u => new SysNoticeUser
        {
            NoticeId = notice.Id,
            UserId = u,
            AppJumpUrl = input.AppJumpUrl
        }).ToList();
        await _sysNoticeUserRep.InsertRangeAsync(noticeUserList);

        // 广播所有在线账号
        await _sysOnlineUserService.PublicNotice(notice, userIdList);
    }
    #endregion

    /// <summary>
    /// 设置通知公告已读状态
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("设置通知公告已读状态")]
    public async Task<SysNotice> SetRead(NoticeInput input)
    {
        var model = await _sysNoticeUserRep.Context.Queryable<SysNoticeUser>()
             .Includes(r => r.SysNotice)
             .FirstAsync(u => u.NoticeId == input.Id && u.UserId == _userManager.UserId);
        model.ReadStatus = NoticeUserStatusEnum.READ;
        model.ReadTime = DateTime.Now;
        await _sysNoticeUserRep.Context.MyUpdateable(model)
            .WhereColumns(new string[] { nameof(SysNoticeUser.NoticeId), nameof(SysNoticeUser.UserId) }).ExecuteCommandAsync();
        return model.SysNotice;
    }

    /// <summary>
    /// 获取接收的通知公告
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("获取接收的通知公告")]
    public async Task<SqlSugarPagedList<SysNoticeUser>> GetPageReceived([FromQuery] PageNoticeInput input)
    {
        return await _sysNoticeRep.AsSugarClient().Queryable<SysNoticeUser>().Includes(u => u.SysNotice)
            .Where(u => u.UserId == _userManager.UserId)
            .WhereIF(!string.IsNullOrWhiteSpace(input.Title), u => u.SysNotice.Title.Contains(input.Title.Trim()))
            .WhereIF(input.Type is > 0, u => u.SysNotice.Type == input.Type)
            .OrderBy(u => u.SysNotice.CreateTime, OrderByType.Desc)
            .ToPagedListAsync(input.Page, input.PageSize);
    }

    /// <summary>
    /// 获取未读的通知公告App
    /// </summary>
    /// <returns></returns>
    [DisplayName("获取未读的通知公告App")]
    [HttpPost]
    public async Task<SqlSugarPagedList<SysNotice>> QueryUnReadListApp(PageNoticeInput input)
    {
        var noticeUserList = await _sysNoticeRep.AsSugarClient().Queryable<SysNoticeUser>().Includes(u => u.SysNotice)
            .WhereIF(input.Type.HasValue, u => SqlFunc.Subqueryable<SysNotice>().Where(c => c.Id == u.NoticeId && c.Type == input.Type).Any())
            .WhereIF(input.Status.HasValue, u => u.ReadStatus == input.Status.Value)
             .WhereIF(!input.Status.HasValue, u => u.ReadStatus == NoticeUserStatusEnum.UNREAD)
            .WhereIF(!input.SearchKey.IsNullOrEmptyOrNullString(),
            u => SqlFunc.Subqueryable<SysNotice>().Where(c => c.Id == u.NoticeId && c.Title.Contains(input.SearchKey)).Any())
            .Where(u => u.UserId == _userManager.UserId)
            .OrderBy(u => u.SysNotice.CreateTime, OrderByType.Desc)
            .ToPagedListAsync(input.Page, input.PageSize);
        var notices = noticeUserList.Items.Select(t => t.SysNotice).ToList();


        var totalPages = noticeUserList.PageSize > 0 ? (int)Math.Ceiling(noticeUserList.Total / (double)noticeUserList.PageSize) : 0;
        return new SqlSugarPagedList<SysNotice>
        {
            Page = noticeUserList.Page,
            PageSize = noticeUserList.PageSize,
            Items = notices,
            Total = noticeUserList.Total,
            TotalPages = totalPages,
            HasNextPage = noticeUserList.Page < totalPages,
            HasPrevPage = noticeUserList.Page - 1 > 0
        };
    }

    /// <summary>
    /// 获取未读的通知公告
    /// </summary>
    /// <returns></returns>
    [DisplayName("获取未读的通知公告")]
    public async Task<List<SysNotice>> GetUnReadList()
    {
        var noticeUserList = await _sysNoticeRep.AsSugarClient().Queryable<SysNoticeUser>().Includes(u => u.SysNotice)
            .Where(u => u.UserId == _userManager.UserId && u.ReadStatus == NoticeUserStatusEnum.UNREAD)
            .OrderBy(u => u.SysNotice.CreateTime, OrderByType.Desc).ToListAsync();
        return noticeUserList.Select(t => t.SysNotice).ToList();
    }

    /// <summary>
    /// 创建业务消息
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    public async Task CreateBusinessVSsage(BusinessNoticeInput input)
    {
        input.Type = NoticeTypeEnum.NOTICE;
        if (input.PublicUserId <= 0)
        {
            input.PublicUserId = 1300000000101;
            input.PublicOrgName = "超级管理员";
        }
        input.Status = NoticeStatusEnum.DRAFT;

        var notice = input.Adapt<AddNoticeInput>();
        notice.Id = await AddNotice(notice);
        await Public(new NoticeInput { Id = notice.Id });
    }
    /// <summary>
    /// 初始化通知公告信息
    /// </summary>
    /// <param name="notice"></param>
    [NonAction]
    private async Task InitNoticeInfo(SysNotice notice)
    {
        if (_userManager._TemphttpContextAccessor.HttpContext != null)
        {
            notice.PublicUserId = _userManager.UserId;
            notice.PublicUserName = _userManager.RealName;
            notice.PublicOrgId = _userManager.OrgId;
        }
        if (notice.ReceiveOrgId.HasValue)
        {
            var org = await _sysOrgService.GetOrg(notice.ReceiveOrgId.Value);
            notice.ReceiveOrgName = org.Name;
        }

    }
}